package com.sicheng.lc.周赛.分类.dp.rmq;

/**
 * @author zsc
 * @version 1.0
 * @date 2022/7/8 19:55
 */
public class 子数组范围和 {
    static int[][] dpMax = new int[1000][11];
    static int[][] dpMin = new int[1000][11];
    static int[] K =new int[1000];
    static int n;

    public long subArrayRanges(int[] nums) {
        init(nums);
        long res = 0;
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j < nums.length; j++) {
                res += queryMax(i, j) - queryMin(i, j);
            }
        }
        return res;
    }

    private void init(int[] nums) {
        n = nums.length;
        for (int i = 0; i < n; i++) {
            dpMax[i][0] = nums[i];
            dpMin[i][0] = nums[i];
        }

        for (int j = 1; 1 << j <= n; j++) {
            for (int i = 0; i + (1 << j) - 1 < n; i++) {
                dpMax[i][j] = Math.max(dpMax[i][j - 1], dpMax[i + (1 << (j - 1))][j - 1]);
                dpMin[i][j] = Math.min(dpMin[i][j - 1], dpMin[i + (1 << (j - 1))][j - 1]);
            }
        }
    }

    int queryMax(int l, int r) {
        int n = r - l + 1;
        int k = (int) (Math.log(n) / Math.log(2));
        return Math.max(dpMax[l][k], dpMax[r - (1 << k) + 1][k]);
    }

    int queryMin(int l, int r) {
        int n = r - l + 1;
        int k = (int) (Math.log(n) / Math.log(2));
        return Math.min(dpMin[l][k], dpMin[r - (1 << k) + 1][k]);
    }


}
